package com.nevermore.shellexe;

import android.os.Process;
import android.os.SystemClock;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @author xct
 * create on: 2023/4/26 17:00
 */
public class APM{

    // Linux 默认时钟频率为 100 HZ
    private int CLK_TCK = 100;
    // 上次的CPU使用时间
    private long lastUsedCPUTime = 0L;
    // 上次的CPU记录时间
    private long lastRecordCPUTime = SystemClock.uptimeMillis();
    // 存储 CPU 使用信息的文件
    private final File pidStatFile = new File("/proc/" + Process.myPid() + "/stat");
    // 获取 时钟频率 的命令
    private final String[] cmd = {"sh", "-c", "getconf CLK_TCK"};

    /**
     * 计算方法 ∆(uTime + sTime) / ∆upTimeMillis / 1000 * CLK_TCK / CORE_COUNT
     * 计算方法 进程运行时间片数 / (已过去时间 * 时钟频率 * 可用核心数)
     *
     * @return 当前CPU使用率%(from 0 to 100)
     */
    public float getCpuUsage() {
        try (FileInputStream inputStream = new FileInputStream(pidStatFile);
             InputStreamReader reader = new InputStreamReader(inputStream);
             BufferedReader bufferedReader = new BufferedReader(reader)
        ) {
            String line = bufferedReader.readLine();
            String[] res = line.split(" ");
            // 进程在用户态运行的时间
            long uTime = Long.parseLong(res[13]);
            // 进程在内核态运行的时间
            long sTime = Long.parseLong(res[14]);
            // 本次运行总时间
            long usedTime = (uTime + sTime) - lastUsedCPUTime;

            long currentTime = SystemClock.uptimeMillis();
            // 获得已过去时间 ms ==> s ==> Clock Tick
            float elapsedTime = (currentTime - lastRecordCPUTime) / 1000f * CLK_TCK;

            lastUsedCPUTime = uTime + sTime;
            lastRecordCPUTime = currentTime;

            float usage = usedTime / elapsedTime * 100;
            return usage / Runtime.getRuntime().availableProcessors();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0f;
    }

    /**
     * 确保时钟频率正确，以防厂商定制
     * 测试 坚果1 Android5.1 获取参数失败，但默认也是 100
     */
    private void configClkTck() {
        try {
            java.lang.Process process = Runtime.getRuntime().exec(cmd);
            try (InputStream inputStream= process.getInputStream();
                 InputStreamReader reader = new InputStreamReader(inputStream);
                 BufferedReader bufferedReader = new BufferedReader(reader)){
                CLK_TCK = Integer.parseInt(bufferedReader.readLine());
            }
            process.destroy();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
